﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
using PotatoSoft.VOCTS.Workbench;

namespace PotatoSoft.Middleware
{
    /// <summary>
    /// Klasa odpowiedzialna za ViewModel. Klasa ta implementuje wzorzec Singleton.
    /// Autor: Jakub Szatkowski
    /// </summary>
    public class VisualOctStudioCore
    {
        private static VisualOctStudioCore Instance;

        private VisualOctStudioCore()
        {
        }

        /// <summary>
        /// Funkcja winapi do ładowania dynamicznego bibliotek niezarządzanych.
        /// </summary>
        /// <param name="dllName">Nazwa biblioteki</param>
        /// <returns>Jeżeli zero to biblioteka nie wczytała się poprawnie</returns>
        [DllImport("kernel32")]
        static extern int LoadLibrary(string dllName);

        /// <summary>
        /// Funkcja winapi do sprawdzania kodu błędu po wykonywaniu funkcji winapi.
        /// </summary>
        /// <returns>Systemowy kod błeędu</returns>
        [DllImport("kernel32")]
        static extern int GetLastError();

        /// <summary>
        /// Statyczna funkcja do pobrania instancji klasy - reazlizuje Singleton
        /// </summary>
        /// <returns>Instancja klasy VisualOctStudioViewModel</returns>
        public static VisualOctStudioCore GetInstance()
        {
            if (Instance == null)
                Instance = new VisualOctStudioCore();
            return Instance;
        }

        /// <summary>
        /// Delegat, który pozwala przechowywać funkcję, która będzie wywoływana na załadowanie boblioteki.
        /// </summary>
        /// <param name="libraryName">Nazwa załadowanej biblioteki</param>
        /// <param name="countOfResourceToLoad">Ilość pozostałych bibliotek do załadowania</param>
        public delegate void OnLoadedLibraryDelegate(string libraryName, int countOfResourceToLoad);

        private OnLoadedLibraryDelegate OnLoadedLibrary;

        /// <summary>
        /// Funkcja do zarejestrowania delegata, który będzie wykonany po załadowaniu biblioteki.
        /// </summary>
        /// <param name="onLoadedLibraries"></param>
        public void SetOnLoadedLibraries(OnLoadedLibraryDelegate onLoadedLibraries)
        {
            this.OnLoadedLibrary = onLoadedLibraries;
        }

        /// <summary>
        /// Funkcja do załadowania wszystkich niezarządzanych bibliotek.
        /// </summary>
        public void LoadLibraries()
        {
            string dllList = Resource.dllsList;
            string[] dlls = dllList.Split(',');
            for (int i = 0; i < dlls.Length; i++)
            {
                int ptr = LoadLibrary(dlls[i]);
                if (ptr == 0)
                {
                    int er = GetLastError();
                    throw new LoadResourceException("Cannot load library: " + dlls[i]+", Error Code: "+er);
                }
                OnLoadedLibrary(dlls[i], dlls.Length - i-1);
            }
        }

        private VisualOctStudioData data=new VisualOctStudioData();
        public VisualOctStudioData Data
        {
            get { return data; }
        }
    }
}
